<?php
namespace Imi\Redis;

use Imi\Util\Defer;

/**
 * @method mixed deferAppend($key, $value)
 * @method mixed deferAuth($password)
 * @method mixed deferBgSave()
 * @method mixed deferBgrewriteaof()
 * @method mixed deferBitcount($key)
 * @method mixed deferBitop($operation, $ret_key, $key, ...$other_keys)
 * @method mixed deferBitpos($key, $bit, $start = null, $end = null)
 * @method mixed deferBlPop($key, $timeout_or_key, ...$extra_args)
 * @method mixed deferBrPop($key, $timeout_or_key, ...$extra_args)
 * @method mixed deferBrpoplpush($src, $dst, $timeout)
 * @method mixed deferClearLastError()
 * @method mixed deferClient($cmd, ...$args)
 * @method mixed deferClose()
 * @method mixed deferCommand(...$args)
 * @method mixed deferConfig($cmd, $key, $value = null)
 * @method mixed deferConnect($host, $port, $timeout = null, $retry_interval = null)
 * @method mixed deferDbSize()
 * @method mixed deferDebug($key)
 * @method mixed deferDecr($key)
 * @method mixed deferDecrBy($key, $value)
 * @method mixed deferDelete($key, ...$other_keys)
 * @method mixed deferDiscard()
 * @method mixed deferDump($key)
 * @method mixed deferEcho($msg)
 * @method mixed deferEval($script, $args = null, $num_keys = null)
 * @method mixed deferEvalsha($script_sha, $args = null, $num_keys = null)
 * @method mixed deferExec()
 * @method mixed deferExists($key, ...$other_keys)
 * @method mixed deferExpireAt($key, $timestamp)
 * @method mixed deferFlushAll()
 * @method mixed deferFlushDB()
 * @method mixed deferGeoadd($key, $lng, $lat, $member, ...$other_triples)
 * @method mixed deferGeodist($key, $src, $dst, $unit = null)
 * @method mixed deferGeohash($key, $member, ...$other_members)
 * @method mixed deferGeopos($key, $member, ...$other_members)
 * @method mixed deferGeoradius($key, $lng, $lan, $radius, $unit, array $opts = null)
 * @method mixed deferGeoradiusbymember($key, $member, $radius, $unit, array $opts = null)
 * @method mixed deferGet($key)
 * @method mixed deferGetAuth()
 * @method mixed deferGetBit($key, $offset)
 * @method mixed deferGetDBNum()
 * @method mixed deferGetHost()
 * @method mixed deferGetKeys($pattern)
 * @method mixed deferGetLastError()
 * @method mixed deferGetMode()
 * @method mixed deferGetMultiple(array $keys)
 * @method mixed deferGetOption($option)
 * @method mixed deferGetPersistentID()
 * @method mixed deferGetPort()
 * @method mixed deferGetRange($key, $start, $end)
 * @method mixed deferGetReadTimeout()
 * @method mixed deferGetSet($key, $value)
 * @method mixed deferGetTimeout()
 * @method mixed deferHDel($key, $member, ...$other_members)
 * @method mixed deferHExists($key, $member)
 * @method mixed deferHGet($key, $member)
 * @method mixed deferHGetAll($key)
 * @method mixed deferHIncrBy($key, $member, $value)
 * @method mixed deferHIncrByFloat($key, $member, $value)
 * @method mixed deferHKeys($key)
 * @method mixed deferHLen($key)
 * @method mixed deferHMget($key, array $keys)
 * @method mixed deferHMset($key, array $pairs)
 * @method mixed deferHSet($key, $member, $value)
 * @method mixed deferHSetNx($key, $member, $value)
 * @method mixed deferHStrLen($key, $member)
 * @method mixed deferHVals($key)
 * @method mixed deferHscan($str_key, &$i_iterator, $str_pattern = null, $i_count = null)
 * @method mixed deferIncr($key)
 * @method mixed deferIncrBy($key, $value)
 * @method mixed deferIncrByFloat($key, $value)
 * @method mixed deferInfo($option = null)
 * @method mixed deferIsConnected()
 * @method mixed deferLGet($key, $index)
 * @method mixed deferLGetRange($key, $start, $end)
 * @method mixed deferLInsert($key, $position, $pivot, $value)
 * @method mixed deferLPop($key)
 * @method mixed deferLPush($key, $value)
 * @method mixed deferLPushx($key, $value)
 * @method mixed deferLRemove($key, $value, $count)
 * @method mixed deferLSet($key, $index, $value)
 * @method mixed deferLSize($key)
 * @method mixed deferLastSave()
 * @method mixed deferListTrim($key, $start, $stop)
 * @method mixed deferMigrate($host, $port, $key, $db, $timeout, $copy = null, $replace = null)
 * @method mixed deferMove($key, $dbindex)
 * @method mixed deferMset(array $pairs)
 * @method mixed deferMsetnx(array $pairs)
 * @method mixed deferMulti()
 * @method mixed deferObject($field, $key)
 * @method mixed deferPconnect($host, $port, $timeout = null)
 * @method mixed deferPersist($key)
 * @method mixed deferPexpire($key, $timestamp)
 * @method mixed deferPexpireAt($key, $timestamp)
 * @method mixed deferPfadd($key, array $elements)
 * @method mixed deferPfcount($key)
 * @method mixed deferPfmerge($dstkey, array $keys)
 * @method mixed deferPing()
 * @method mixed deferPipeline()
 * @method mixed deferPsetex($key, $expire, $value)
 * @method mixed deferPsubscribe(array $patterns)
 * @method mixed deferPttl($key)
 * @method mixed deferPublish($channel, $message)
 * @method mixed deferPubsub($cmd, ...$args)
 * @method mixed deferPunsubscribe($pattern, ...$other_patterns)
 * @method mixed deferRPop($key)
 * @method mixed deferRPush($key, $value)
 * @method mixed deferRPushx($key, $value)
 * @method mixed deferRandomKey()
 * @method mixed deferRawcommand($cmd, ...$args)
 * @method mixed deferRenameKey($key, $newkey)
 * @method mixed deferRenameNx($key, $newkey)
 * @method mixed deferRestore($ttl, $key, $value)
 * @method mixed deferRole()
 * @method mixed deferRpoplpush($src, $dst)
 * @method mixed deferSAdd($key, $value)
 * @method mixed deferSAddArray($key, array $options)
 * @method mixed deferSContains($key, $value)
 * @method mixed deferSDiff($key, ...$other_keys)
 * @method mixed deferSDiffStore($dst, $key, ...$other_keys)
 * @method mixed deferSInter($key, ...$other_keys)
 * @method mixed deferSInterStore($dst, $key, ...$other_keys)
 * @method mixed deferSMembers($key)
 * @method mixed deferSMove($src, $dst, $value)
 * @method mixed deferSPop($key)
 * @method mixed deferSRandMember($key, $count = null)
 * @method mixed deferSRemove($key, $value)
 * @method mixed deferSSize($key)
 * @method mixed deferSUnion($key, ...$other_keys)
 * @method mixed deferSUnionStore($dst, $key, ...$other_keys)
 * @method mixed deferSave()
 * @method mixed deferScan(&$i_iterator, $str_pattern = null, $i_count = null)
 * @method mixed deferScript($cmd, ...$args)
 * @method mixed deferSelect($dbindex)
 * @method mixed deferSet($key, $value, $timeout = null, $opt = null)
 * @method mixed deferSetBit($key, $offset, $value)
 * @method mixed deferSetOption($option, $value)
 * @method mixed deferSetRange($key, $offset, $value)
 * @method mixed deferSetTimeout($key, $timeout)
 * @method mixed deferSetex($key, $expire, $value)
 * @method mixed deferSetnx($key, $value)
 * @method mixed deferSlaveof($host = null, $port = null)
 * @method mixed deferSlowlog($arg, $option = null)
 * @method mixed deferSort($key, array $options = null)
 * @method mixed deferSortAsc($key, $pattern = null, $get = null, $start = null, $end = null, $getList = null)
 * @method mixed deferSortAscAlpha($key, $pattern = null, $get = null, $start = null, $end = null, $getList = null)
 * @method mixed deferSortDesc($key, $pattern = null, $get = null, $start = null, $end = null, $getList = null)
 * @method mixed deferSortDescAlpha($key, $pattern = null, $get = null, $start = null, $end = null, $getList = null)
 * @method mixed deferSscan($str_key, &$i_iterator, $str_pattern = null, $i_count = null)
 * @method mixed deferStrlen($key)
 * @method mixed deferSubscribe(array $channels)
 * @method mixed deferSwapdb($srcdb, $dstdb)
 * @method mixed deferTime()
 * @method mixed deferTtl($key)
 * @method mixed deferType($key)
 * @method mixed deferUnlink($key, ...$other_keys)
 * @method mixed deferUnsubscribe($channel, ...$other_channels)
 * @method mixed deferUnwatch()
 * @method mixed deferWait($numslaves, $timeout)
 * @method mixed deferWatch($key, ...$other_keys)
 * @method mixed deferZAdd($key, $score, $value)
 * @method mixed deferZCard($key)
 * @method mixed deferZCount($key, $min, $max)
 * @method mixed deferZDelete($key, $member, ...$other_members)
 * @method mixed deferZDeleteRangeByRank($key, $start, $end)
 * @method mixed deferZDeleteRangeByScore($key, $min, $max)
 * @method mixed deferZIncrBy($key, $value, $member)
 * @method mixed deferZInter($key, array $keys, ?array $weights = null, $aggregate = null)
 * @method mixed deferZLexCount($key, $min, $max)
 * @method mixed deferZRange($key, $start, $end, $scores = null)
 * @method mixed deferZRangeByLex($key, $min, $max, $offset = null, $limit = null)
 * @method mixed deferZRangeByScore($key, $start, $end, array $options = null)
 * @method mixed deferZRank($key, $member)
 * @method mixed deferZRemRangeByLex($key, $min, $max)
 * @method mixed deferZRevRange($key, $start, $end, $scores = null)
 * @method mixed deferZRevRangeByLex($key, $min, $max, $offset = null, $limit = null)
 * @method mixed deferZRevRangeByScore($key, $start, $end, array $options = null)
 * @method mixed deferZRevRank($key, $member)
 * @method mixed deferZScore($key, $member)
 * @method mixed deferZUnion($key, array $keys, ?array $weights = null, $aggregate = null)
 * @method mixed deferZscan($str_key, &$i_iterator, $str_pattern = null, $i_count = null)
 * @method mixed deferDel($key, ...$other_keys)
 * @method mixed deferEvaluate($script, $args = null, $num_keys = null)
 * @method mixed deferEvaluateSha($script_sha, $args = null, $num_keys = null)
 * @method mixed deferExpire($key, $timeout)
 * @method mixed deferKeys($pattern)
 * @method mixed deferLLen($key)
 * @method mixed deferLindex($key, $index)
 * @method mixed deferLrange($key, $start, $end)
 * @method mixed deferLrem($key, $value, $count)
 * @method mixed deferLtrim($key, $start, $stop)
 * @method mixed deferMget(array $keys)
 * @method mixed deferOpen($host, $port, $timeout = null, $retry_interval = null)
 * @method mixed deferPopen($host, $port, $timeout = null)
 * @method mixed deferRename($key, $newkey)
 * @method mixed deferSGetMembers($key)
 * @method mixed deferScard($key)
 * @method mixed deferSendEcho($msg)
 * @method mixed deferSismember($key, $value)
 * @method mixed deferSrem($key, $value)
 * @method mixed deferSubstr($key, $start, $end)
 * @method mixed deferZRem($key, $member, ...$other_members)
 * @method mixed deferZRemRangeByRank($key, $min, $max)
 * @method mixed deferZRemRangeByScore($key, $min, $max)
 * @method mixed deferZRemove($key, $member, ...$other_members)
 * @method mixed deferZRemoveRangeByScore($key, $min, $max)
 * @method mixed deferZReverseRange($key, $start, $end, $scores = null)
 * @method mixed deferZSize($key)
 * @method mixed deferZinterstore($key, array $keys, ?array $weights = null, $aggregate = null)
 * @method mixed deferZunionstore($key, array $keys, ?array $weights = null, $aggregate = null)
 */
class CoroutineRedisHandler extends \Swoole\Coroutine\Redis
{
    /**
     * 是否使用序列化
     *
     * @var boolean
     */
    private $__serialize;

    use TFixSwoole;

    public function __call($name, $arguments)
    {
        if(isset($name[5]) && 'defer' === substr($name, 0, 5))
        {
            $this->setDefer(true);
            $methodName = substr($name, 5);
            $result = $this->$methodName(...$arguments);
            $callable = function(){
                return $this->recv();
            };
            $defer = new Defer($callable);
            return $defer;
        }
        return false;
    }

    public function connect($host, $port = null, $serialize = null)
    {
        $this->__serialize = $serialize;
        return parent::connect($host, $port, $serialize);
    }

    public function _serialize($value)
    {
        if($this->__serialize)
        {
            return serialize($value);
        }
        else
        {
            return $value;
        }
    }
}